The use of object-oriented programming techniques can facilitate the development of complex computer programs. Programming languages that support object-oriented techniques have been developed. One such programming language is C++. The C++ programming language is described in "The C++ Language Reference," published by Microsoft Corporation, which is hereby incorporated by reference.
Two common characteristics of object-oriented programming languages are support for data encapsulation and data type inheritance. Data encapsulation refers to the coupling of data to the functions that operate on the data. Inheritance refers to the ability to define a data type as an extension of other data types. An instance of a data type that couples data and functions is referred to as an "object."
An object is a run time structure for a user-defined type (a class type) that may contain data members and function members. Each class has a class definition that specifies its data members and function members. Each object is declared to be a certain class type. In a preferred embodiment, the run time data structures of an object conforms to the model defined in U.S. Pat. No. 5,297,284, entitled "Method and System for Implementing Virtual Functions and Virtual Base Classes and Setting a This Pointer for an Object-Oriented Programming Language," which is hereby incorporated by reference.
FIG. 1 is a block diagram illustrating typical data structures used to represent an object. The data structures comprise instance data structure 101, virtual function table 102, and the function members 103, 104, and 105. The instance data structure 102 contains a pointer to the virtual function table 102 and contains data members. The virtual function table 102 contains an entry for each virtual function member defined for the object. Each entry contains a reference to the code that implements the corresponding function member.
It is often useful for two computer programs to access the same instance of an object. For example, a first computer program instantiates an object in shared memory and notifies a second computer program of the location of the object. The second computer program then accesses the object in shared memory. However, to access the object, the second computer program typically needs to be written and compiled with the class definition of the object. Without the class definition, the second computer program would not know how to access the data members and function members of the object. Thus, a computer program is written and compiled with the class definition for each object it wishes to share with another computer program.
When the developer of a computer program wishes to allow other computer programs to access its objects, the developer publishes the class definitions of its objects. The developers of other computer programs could then incorporate the published class definitions into their computer programs. One skilled in the art would appreciate that this publication may incorporate a "header" file containing the class definitions. The developers of other computer programs could then write their computer programs to access objects defined in the header file and "include" the header file in the source code for the computer programs. The source code is then compiled. When the compiler encounters a class variable, it generates code based on the class definition. The process by which a variable is associated with its class definition is referred to as binding. (Binding in general refers to the associating of two pieces of information with one another.) Binding that occurs at compile time is referred to as early or static binding. Binding that occurs at run time is referred to as late or dynamic binding.
Because prior methods require that a class definition be available when developing a computer program, there has been limited sharing of objects between computer programs developed by independent developers. This limited sharing occurs because, for example, it is difficult to distribute class definitions to independent developers, who may be located throughout the world, in a timely manner. Similarly, it is difficult to distribute updates to the class definition and difficult for the developers to integrate these updates and distribute updated versions of the computer programs to users. These difficulties are compounded when a computer program incorporates class definitions provided by several developers.
To help overcome these difficulties by alleviating the need to have class definitions available at compile time, developers are cooperating to access objects through standard "interfaces. " An interface is an abstract class with no data members and whose virtual functions have no implementation (are pure). An abstract class is a class in which a virtual function member is pure.
The following class definition is an example definition of an interface. This definition allows a program to access a document object of a word processing program. (One skilled in the art would appreciate that interfaces for other types of objects could be defined and used using analogous techniques.) By providing an implementation of this interface, any word processing program can allow its document objects to be accessed by other programs. The other programs are compiled using the interface definition. At run time, the other programs can request a pointer to a document object instantiated by the word processing program. Once the pointer is received, the other program can access the methods defined in the interface.
______________________________________ class IDocument { virtual void Save( ) = 0; virtual void GetPara( ) = 0; virtual void Select( ) = 0; virtual void CreateTable( ) = 0; . . . } ______________________________________
The developer of a word processing program would need to provide an implementation of each function of the interface to allow the word processing objects to be accessed by other programs.
A word processing developer may wish, however, to implement only certain function members and not all the function members of the interface. For example, a word processing developer may not want to implement table support (e.g., the CreateTable function member), but may want to support all other function members. To allow a word processing developer to support only some of the function members, while still allowing objects to be accessed, multiple interfaces for document objects may be defined. For example, the interfaces IDocTable and IDocBasic may be defined for a document object as follows.
______________________________________ class IDocTable { virtual void CreateTable( ) = 0; } class IDocBasic { virtual void Save( ) = 0; virtual void GetPara( ) = 0; virtual void Select( ) = 0; . . . } ______________________________________
Each word processing developer would implement the IDocBasic interface and, optionally, the IDocTable interface.
At run time, the other programs would need to determine whether a document object to be accessed supports the IDocTable interface. To make this determination, another interface is defined (that each document object implements) with a function member that indicates which interfaces are implemented for the object. This interface is known as IUnknown and is defined by the following.
______________________________________ class IUnknown { boolean QueryInterface (InterfaceID, void*) = 0; . . . } ______________________________________
The IUnknown interface defines the function member (method) QueryInterface. The method QueryInterface is passed an interface identifier (e.g., "IDocTable") and returns a pointer to the identified interface for the object for which the method is invoked. If the object does not support the interface, then the method returns a false. The following definitions illustrate the use of the IUnknown interface.
______________________________________ class IDocTable:IUnknown { virtual void CreateTable( ) = 0; } class IDocBasic:IUnknown { virtual void Save( ) = 0; virtual void GetPara( ) = 0; virtual void Select( ) = 0; . . . } ______________________________________
FIG. 2 is a block diagram illustrating a sample data structure of a document object. The document object comprises interface data structure 201, IDocBasic interface data structure 202, IDocTable interface data structure 205, and methods 208 through 212. The interface data structure 201 contains a pointer to each interface implemented and may contain data members of the implementation. The IDocBasic interface data structure 202 contains instance data structure 203 and virtual function table 204. Each entry in the virtual function table 204 points to a method defined for the IDocBasic interface. The IDocTable interface data structure 205 contains instance data structure 206 and virtual function table 207. Each entry in the virtual function table 207 contains a pointer to a method defined in the IDocTable interface. Since the IDocBasic and IDocTable interfaces virtually inherit the IUnknown interface, each virtual function table 204 and 207 contains a pointer to the method QueryInterface 208.
The following pseudocode illustrates how other programs determine whether a document object supports the IDocTable interface. EQU if (pIDocBasic-&gt;QueryInterface("IDocTable",& pIDocTable)) .backslash.*IDocTable supported else .backslash.*IDocTable not supported
The pointer pIDocBasic is a pointer the IDocBasic interface of the object. If the object supports the IDocTable interface, the method QueryInterface sets the pointer pIDocTable to point to the IDocTable data structure and returns true as its value. The other programs can retrieve a pointer pIDocBasic to an open document object by invoking a function whose prototype is published with the interface definitions and whose code is provided by the word processing developer. At run time, the other programs link to the function.
Although the use of multiple interfaces for an object facilitates accessing of objects, the developer of an object needs to publish the interface definitions so that other developers could use the definitions when compiling their programs. It would be desirable to allow programs to share objects without needing to access each of the interface definitions at compile time.